<?php
/**
 * Desc: Service模板
 * User: zdb
 * Date: 2023/6/5
 * Time: 11:22
 */

namespace app\api\service\access;
use think\facade\Db;

class MenuService
{

    private $primaryTable;

    public function __construct()
    {
        $this->primaryTable = "yj_menu";
    }

    public function findRowById($id)
    {
        return Db::table($this->primaryTable)->alias('a')
            ->where('id', '=', $id)
            ->strict(false)
            ->find();
    }

    public function findRowByData($data)
    {
        $condition = $this->assembleFilterCondition($data);
        return Db::table($this->primaryTable)->alias('a')
            ->where($condition)
            ->strict(false)
            ->find();
    }

    public function getListByManyId($arrId)
    {
        $list = Db::table($this->primaryTable)->alias('a')
            ->whereIn('id', $arrId)
            ->select()
            ->toArray();
        return $list;
    }

    public function assembleFilterCondition($data)
    {
        $condition = ['a.status > 0'];

        if (!empty($data['title'])) {
            $condition[] = "title like '%" . $data['title'] . "%'";
        }


        if (!empty($data['menu_level'])) {
            $condition[] = "a.menu_level = " . $data['menu_level'];
        }


        return empty($condition) ? "" : implode(" AND ", $condition);
    }

    public function getListNoPage($data = [])
    {
        $condition = $this->assembleFilterCondition($data);
        $res = Db::table($this->primaryTable)->alias('a')
            ->where($condition)
            ->select()
            ->toArray();
        return $res;
    }

    public function getListWithPage($data, $pageIndex = 1, $pageSize = 30)
    {
        $offset = ($pageIndex - 1) * $pageSize;
        $condition = $this->assembleFilterCondition($data);
        $res = Db::table($this->primaryTable)
            ->where($condition)
            ->limit($offset, $pageSize)
            ->order('id desc')
            ->select();
        return $res;
    }

    public function getTotalNum($data)
    {
        $condition = $this->assembleFilterCondition($data);
        $num = Db::table($this->primaryTable)->alias('a')
            ->where($condition)
            ->count();
        return $num;
    }

    public function createRow($data)
    {
        $data['status'] = isset($data['status']) ? $data['status']:1;
        $res = Db::table($this->primaryTable)
            ->strict(false)
            ->insert($data, true);
        return $res;
    }

    public function createManyRow($data)
    {
        $res = Db::table($this->primaryTable)
            ->strict(false)
            ->duplicate($data)
            ->insertAll($data, true);
        return $res;
    }

    public function updateRowById($id, $data)
    {
        $res = Db::table($this->primaryTable)->alias('a')
            ->where('id', '=', $id)
            ->strict(false)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function updateListByData($condition, $data)
    {
        $condition = $this->assembleFilterCondition($data);
        $res = Db::table($this->primaryTable)->alias('a')
            ->where($condition)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function updateListByManyId($arrId, $data)
    {
        $res = Db::table($this->primaryTable)->alias('a')
            ->whereIn('a.id', $arrId)
            ->strict(false)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function removeRowById($id)
    {
        $data = ['status' => 0];
        $res = Db::table($this->primaryTable)
            ->where('id', '=', $id)
            ->strict(false)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function removeRowByManyId($arrId)
    {
        $data = ['status' => 0];
        $res = Db::table($this->primaryTable)->alias('a')
            ->whereIn('a.id', $arrId)
            ->strict(false)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function removeListByData($data)
    {
        $condition = $this->assembleFilterCondition($data);
        $data = ['status' => 0];
        $res = Db::table($this->primaryTable)->alias('a')
            ->where($condition)
            ->save($data);
        return false !== $res ? true : false;
    }

    public function getTreeList($roleId)
    {
        $list = Db::table($this->primaryTable)->alias('a')
            ->where('a.status > 0')
            ->order('a.menu_level desc,a.parent_menu_id asc, a.sort asc')
            ->select()->toArray();
        $finalList = [];
        $childrenList = [];

        if ($roleId) {
            $relationList = (new RoleMenuService())->getListByRoleId($roleId);
            $listByMenuId = array_column($relationList, 'id', 'menu_id');
            $arrMenuId = array_keys($listByMenuId);
            foreach ($list as &$item) {
                if (in_array($item['id'], $arrMenuId)) {
                    $item['role_menu_id'] = $listByMenuId[$item['id']];
                    $item['checked'] = true;
                } else {
                    $item['role_menu_id'] = 0;
                    $item['checked'] = false;
                }

                $item['children'] = $childrenList[$item['id']] ?? [];
                $item['state'] = "open";
                $parentMenuId = $item['parent_menu_id'];
                if (!isset($childrenList[$parentMenuId])) {
                    $childrenList[$parentMenuId] = [];
                }
                $childrenList[$parentMenuId][] = $item;
                if (0 == $item['parent_menu_id']) {
                    $finalList[] = $item;
                }
            }
        } else {
            foreach ($list as &$item) {
                $item['children'] = $childrenList[$item['id']] ?? [];
                $item['state'] = "open";
                $parentMenuId = $item['parent_menu_id'];
                if (!isset($childrenList[$parentMenuId])) {
                    $childrenList[$parentMenuId] = [];
                }
                $childrenList[$parentMenuId][] = $item;
                if (0 == $item['parent_menu_id']) {
                    $finalList[] = $item;
                }
            }
        }
        return $finalList;
    }

    /**
     * 获取菜单所有父节点
     * @param $menuId
     */
    public function getAllParentMenuId($menuId)
    {
        $list = $this->getListNoPage([]);
        return $this->getParentMenu($list, $menuId);
    }

    public function getParentMenu($list, $menuId)
    {
        $arrId = [];
        foreach ($list as $item) {
            if ($item['id'] == $menuId) {
                if (empty($item['parent_menu_id'])) {
                    break;
                }
                $arrId[] = $item['parent_menu_id'];
                $arrId = array_merge($arrId, $this->getParentMenu($list, $item['parent_menu_id']));
            }
        }
        return $arrId;
    }

    public function getAllChildrenMenuId($menuId)
    {
        $list = $this->getListNoPage();
        return $this->getChildrenMenu($list, $menuId);
    }

    public function getChildrenMenu($list, $menuId)
    {
        $arrId = [];
        foreach ($list as $item) {
            if ($item['parent_menu_id'] == $menuId) {
                $arrId[] = $item['id'];
                $arrId = array_merge($arrId, $this->getChildrenMenu($list, $item['id']));
            }
        }
        return $arrId;
    }

    /**
     * Desc: 获取面板菜单列表，按照层级结构展示
     * @param array $arrMenuId
     * @return array
     * Datetime: 2024/3/4 11:37 by zdb
     */
    public function getPanelList($arrMenuId = [])
    {
        if ($arrMenuId) {
            $list = Db::table($this->primaryTable)->where(['status' => 1])
                ->whereIn('id', $arrMenuId)
                ->order('menu_level desc, sort asc, parent_menu_id asc')->select();
        } else {
            $list = Db::table($this->primaryTable)->where(['status' => 1])->order('menu_level desc, sort asc, parent_menu_id asc')->select();
        }
        $finalData = [];
        $dataByParentId = [];
        foreach ($list as $item) {
            $menuId = $item['id'];
            $parentMenuId = $item['parent_menu_id'];

            if (0 == $parentMenuId) {
                $childrenList = isset($dataByParentId[$menuId]) ? $dataByParentId[$menuId] : [];
                $item['children'] = $childrenList;
                $finalData[] = $item;
            }

            //处理中间层级
            if (0 != $parentMenuId) {
                $childrenList = isset($dataByParentId[$menuId]) ? $dataByParentId[$menuId] : [];
                $item['children'] = $childrenList;
                $dataByParentId[$menuId] = $item;
            }

            //处理最底层
            if (!isset($dataByParentId[$parentMenuId])) {
                $dataByParentId[$parentMenuId] = [];
            }
            $dataByParentId[$parentMenuId][] = $item;
        }
        return $finalData;
    }

    public function getMenuSelectOption($menuLevel)
    {
        $list = Db::table($this->primaryTable)->alias('a')
            ->leftJoin("yj_menu m2", "m2.id = a.parent_menu_id")
            ->leftJoin("yj_menu m1", "m1.id = m2.parent_menu_id")
            ->where('a.menu_level', '=', $menuLevel)
            ->where('a.status', '=', 1)
            ->field("a.*, m2.menu_name_cn as second_menu_name, m1.menu_name_cn as first_menu_name,
             concat_ws('/', m1.menu_name_cn, m2.menu_name_cn, a.menu_name_cn) as menu_path")
            ->select();
        return $list;
    }
}